package v1

import (
	"RoccBlog/api"
	"RoccBlog/global"
	"RoccBlog/model/req_resp"
	v1 "RoccBlog/service/v1"
	"RoccBlog/util"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
)

type CommonController struct {
	api.BaseController
	UserService *v1.UserService
	RoleService *v1.RoleService
}

func init() {
	global.RegisterController(&CommonController{})
}

func (c *CommonController) RegisterController(engine *gin.RouterGroup) {
	c.UserService = global.GetService(v1.UserService{}).(*v1.UserService)
	c.RoleService = global.GetService(v1.RoleService{}).(*v1.RoleService)

	engine.POST("/login", c.Login)
	engine.POST("/register", c.Register)
	engine.GET("/sendEmail", c.SendEmail)
	engine.GET("/logout", c.Logout)
	engine.GET("/getRoleInfo", c.GetRoleInfo)
	engine.POST("/upload", c.Upload)
	engine.GET("/download", c.Download)
}

// Login
// @Tags 通用模块
// @Summary 用户登录
// @Produce  json
// @Param user body req_resp.LoginUserReq required "登录用户"
// @Success 200 {object} api.Result "成功"
// @Router /login [post]
func (c *CommonController) Login(ctx *gin.Context) {
	var loginUser req_resp.LoginUserReq
	err := ctx.ShouldBind(&loginUser)
	if err != nil {
		c.ResponseBadRequest(ctx)
		return
	}

	user, token, err := c.UserService.LoginUser(ctx, loginUser)
	if err != nil {
		c.Response(ctx, http.StatusBadRequest, "登录失败！"+err.Error(), nil)
		return
	}

	c.HandleResponseResult(ctx, err, "登录失败！", gin.H{
		"userInfo": user,
		"token":    token,
	})
}

// Register
// @Tags 通用模块
// @Summary 用户注册
// @Produce  json
// @Param user body req_resp.RegisterUserReq required "注册用户"
// @Success 200 {object} api.Result "成功"
// @Router /register [post]
func (c *CommonController) Register(ctx *gin.Context) {
	var registerUser req_resp.RegisterUserReq
	err := ctx.ShouldBind(&registerUser)
	if err != nil {
		c.ResponseBadRequest(ctx)
		return
	}

	err = c.UserService.Register(ctx, registerUser)
	c.HandleResponseNoResult(ctx, err, "注册用户失败", "注册用户成功")
}

var compile, _ = regexp.Compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$")

// SendEmail
// @Tags 通用模块
// @Summary 用户注册
// @Produce  json
// @Param email query string required "邮箱"
// @Success 200 {object} api.Result "成功"
// @Router /sendEmail [post]
func (c *CommonController) SendEmail(ctx *gin.Context) {
	email := ctx.Query("email")

	if !compile.MatchString(email) {

	}

	err := util.SendEmail(email, "Rocc.cc 注册邮件")
	if err != nil {
		c.Response(ctx, http.StatusInternalServerError, "发送邮件失败"+err.Error(), nil)
	}
	c.Response(ctx, http.StatusOK, "邮件发送成功", nil)
}

// Logout
// @Tags 通用模块
// @Summary 用户注册
// @Produce  json
// @Success 200 {object} api.Result "成功"
// @Router /logout [get]
func (c *CommonController) Logout(ctx *gin.Context) {
	var err error = c.UserService.Logout(ctx)
	if err != nil {
		c.Response(ctx, http.StatusUnauthorized, "退出失败", nil)
		return
	}
	c.Response(ctx, http.StatusOK, "退出成功", nil)
}

// GetRoleInfo
// @Tags 通用模块
// @Summary 获取角色信息
// @Produce  json
// @Success 200 {object} api.Result "成功"
// @Router /getRoleInfo [get]
func (c *CommonController) GetRoleInfo(ctx *gin.Context) {

	//获取角色id
	id, err := strconv.Atoi(ctx.Query("id"))
	if err != nil {
		c.ResponseBadRequest(ctx)
		return
	}

	//查询角色id信息
	roleInfo, err := c.RoleService.FindByIdInfo(ctx, id)

	c.HandleResponseResult(ctx, err, "查询角色信息失败", roleInfo)
}

// Upload
// @Tags 通用模块
// @Summary  上传文件
// @Produce  json
// @Param file form multipart.FileHeader required "上传文件"
// @Success 200 {object} api.Result "成功"
// @Router /upload [post]
func (c *CommonController) Upload(ctx *gin.Context) {
	file, err := ctx.FormFile("file")
	if err != nil {
		// 没有上传文件
		c.ResponseBadRequest(ctx)
		return
	}

	//获取文件后缀名
	suffixName := strings.Split(file.Filename, ".")[1]

	//获取uuid
	filename := fmt.Sprintf("%s.%s", uuid.New().String(), suffixName)
	_, err = os.Stat("./uploads/" + filename)

	//保存文件
	ctx.SaveUploadedFile(file, "./uploads/"+filename)

	c.Response(ctx, http.StatusOK, "上传成功", "/download?fileName="+filename)
}

// Download
// @Tags 通用功能
// @Summary 文件下载
// @Param fileName query string required "文件名"
// @Success 200 {object} multipart.FileHeader "成功"
// @Router /download [get]
func (c *CommonController) Download(ctx *gin.Context) {
	fileName := ctx.Query("fileName")
	if fileName == "" {
		c.ResponseBadRequest(ctx)
		return
	}

	if _, err := os.Stat("./uploads/" + fileName); err != nil {
		c.ResponseBadRequest(ctx)
		return
	}

	ctx.FileAttachment("./uploads/"+fileName, fileName)
}
